---
title: Using KEYS_ONLY Global Secondary Indexes
description: Querying indexes with KEYS_ONLY projections
keywords:
  - electrodb
  - docs
  - concepts
  - dynamodb
  - query
  - entity
  - attribute
  - schema
  - index
  - keys_only
  - projection
layout: ../../../layouts/MainLayout.astro
---

It is common to define a Global Secondary Index using a `KEYS_ONLY` projection. This `ProjectionType` helps keep indexes as small as possible which can reduce cost. Unfortunately, because ElectroDB abstracts away key management, querying this index type with ElectroDB requires unique considerations.

## Example Setup

<blockQuote>
    <h4>Example Setup</h4>
    <details>
        <summary>Table Definition</summary>

        ```json
        {
            "TableName": "electro",
            "KeySchema":[
        {
            "AttributeName":"pk",
            "KeyType":"HASH"
        },
        {
            "AttributeName":"sk",
            "KeyType":"RANGE"
        }
            ],
            "AttributeDefinitions":[
        {
            "AttributeName":"pk",
            "AttributeType":"S"
        },
        {
            "AttributeName":"sk",
            "AttributeType":"S"
        },
        {
            "AttributeName":"gsi1pk",
            "AttributeType":"S"
        },
        {
            "AttributeName":"gsi1sk",
            "AttributeType":"S"
        }
            ],
            "GlobalSecondaryIndexes":[
        {
            "IndexName":"gsi1pk-gsi1sk-index",
            "KeySchema":[
        {
            "AttributeName":"gsi1pk",
            "KeyType":"HASH"
        },
        {
            "AttributeName":"gsi1sk",
            "KeyType":"RANGE"
        }
            ],
            "Projection":{
            "ProjectionType":"ALL"
        }
        }
            ],
            "BillingMode":"PAY_PER_REQUEST"
        }
        ```

    </details>

    <details>
        <summary>Example Entity</summary>

        ```typescript
        import DynamoDB from "aws-sdk/clients/dynamodb";
        import { Entity } from 'electrodb';

        const client = new DynamoDB.DocumentClient();

        const table = 'electro';

        const assets = new Entity({
            model: {
                entity: 'assets',
                version: '1',
                service: 'inventory'
            },
            attributes: {
                assetId: {
                    type: 'string'
                },
                accountId: {
                    type: 'string'
                },
                name: {
                    type: 'string'
                },
                description: {
                    type: 'string'
                },
                city: {
                    type: 'string'
                },
                county: {
                    type: 'string'
                },
                state: {
                    type: 'string'
                },
                zip: {
                    type: 'string'
                }
            },
            indexes: {
                assets: {
                    pk: {
                        field: 'pk',
                        composite: ['accountId']
                    },
                    sk: {
                        field: 'sk',
                        composite: ['assetId']
                    }
                },
                locations: {
                    collection: 'geographics',
                    index: 'gsi1pk-gsi1sk-index',
                    pk: {
                        field: 'gsi1pk',
                        composite: ['state'],
                    },
                    sk: {
                        field: 'gsi1sk',
                        composite: ['county', 'city', 'zip'],
                    }
                }
        }
    }, { table, client });
    ```

    </details>

</blockQuote>

## Hydrating Queries

The execution option `hydrate` can be used instruct ElectroDB to perform a `query` followed by an immediate `batchGet` to retrieve each individual item. Hydrate is available when performing `query`, `match`, or `find` operations.

> \_Note: Without hydration, a `KEYS_ONLY` index will likely fail. This is because ElectroDB adds additional attribute filters to queries to aid with entity isolation. These attributes won't be present on a `KEYS_ONLY` index, so DynamoDB will throw. To circumvent this, checkout the [Returning Keys](#returning-keys) section below.

```typescript
// the locations index (gsi1pk-gsi1sk-index) is a KEYS_ONLY projection
const { data, cursor } = await assets.query
  .locations({ state: "Georgia" })
  .go({ hydrate: true });
```

## Returning Keys

If you do not wish to "hydrate" your query response, you still have ways you can retrieve the keys returned by DynamoDB. The first mechanism is to use the query execution options `{ ignoreOwnership: true, data: 'includeKeys' }`.

> _Note: When using typescript these options do not impact the typing of the returned object so this approach may require casting_

### Include Keys

The query execution options `{ ignoreOwnership: true, data: 'includeKeys' }` allow you to return keys on the `data` array. The option `ignoreOwnership` is also used here to limit filters applied to query to identify item types. ElectroDB filters out items that it cannot identify as belonging to an Entity using identifier attributes (`__edb_e__`, and `__edb_v__`); `KEYS_ONLY` items are then indistinguishable from unidentifiable items.

```typescript
// The elements in the `data` array are just the keys of the index, despite the typing saying otherwise.
const { data, cursor } = await assets.query
  .locations({ state: "Georgia" })
  .go({ ignoreOwnership: true, data: "includeKeys" });
```

### Raw Responses

The query execution option `{ data: 'raw' }` will return the raw response from DynamoDB. This is one way you can access the results of a `KEYS_ONLY` index.

```typescript
// result is the actual DynamoDB response, despite the typing saying otherwise.
const result: any = await assets.query
  .locations({ state: "Georgia" })
  .go({ data: "raw" });
const { Items, LastEvaluatedKey } = result;
```

## References

- [GSI Projection Definition Documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Projection.html)
